home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / m107.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  14KB  |  481 lines

  1. /****************************************************************************
  2.  
  3.     Irem M107 video hardware, Bryan McPhail, mish@tendril.co.uk
  4.  
  5.     Close to M92 hardware, but with 4 playfields, not 3.
  6.     Twice as many colours, twice as many sprites.
  7.  
  8. *****************************************************************************
  9.  
  10.     Port:
  11.         0x80: pf1 Y scroll
  12.         0x82: pf1 X scroll
  13.         0x84: pf2 Y scroll
  14.         0x86: pf2 X scroll
  15.         0x88: pf3 Y scroll
  16.         0x8a: pf3 X scroll
  17.         0x8c: pf4 Y scroll
  18.         0x8e: pf4 X scroll
  19.  
  20.         0x90: pf1 control
  21.         0x92: pf2 control
  22.         0x94: pf3 control
  23.         0x96: pf4 control
  24.  
  25.         0x98: Priority?
  26.         0x9a:
  27.         0x9c:
  28.         0x9e: Raster interrupt value
  29.  
  30.     Playfield control:
  31.         Bit  0x0f00:     Playfield location in VRAM (in steps of 0x1000)
  32.         Bit  0x0080:    0 = Playfield enable, 1 = disable
  33.         Bit  0x0002:    1 = Rowscroll enable, 0 = disable
  34.  
  35. *****************************************************************************/
  36.  
  37. #include "driver.h"
  38. #include "vidhrdw/generic.h"
  39.  
  40. static struct tilemap *pf4_layer,*pf3_layer,*pf2_layer,*pf1_layer;
  41. static int m107_control[0x20];
  42. static unsigned char *m107_spriteram;
  43. unsigned char *m107_vram_data;
  44. int m107_raster_irq_position,m107_sprite_list;
  45.  
  46. static int pf1_vram_ptr,pf2_vram_ptr,pf3_vram_ptr,pf4_vram_ptr;
  47. static int pf1_enable,pf2_enable,pf3_enable,pf4_enable;
  48. static int pf1_rowscroll,pf2_rowscroll,pf3_rowscroll,pf4_rowscroll;
  49.  
  50. /*****************************************************************************/
  51.  
  52. static void get_pf1_tile_info(int tile_index)
  53. {
  54.     int tile,color;
  55.     tile_index = 4*tile_index + pf1_vram_ptr;
  56.  
  57.     tile=m107_vram_data[tile_index]+(m107_vram_data[tile_index+1]<<8);
  58.     if (m107_vram_data[tile_index+3] & 0x10) tile+=0x10000;
  59.     color=m107_vram_data[tile_index+2];
  60.  
  61.     SET_TILE_INFO(0,tile,color&0x7f)
  62.  
  63.     /* Priority 1 = tile appears above sprites */
  64.     tile_info.priority = ((m107_vram_data[tile_index+3]&2)>>1);
  65.     tile_info.flags = TILE_FLIPYX((m107_vram_data[tile_index+3] & 0xc)>>2);
  66. }
  67.  
  68. static void get_pf2_tile_info(int tile_index)
  69. {
  70.     int tile,color;
  71.     tile_index = 4*tile_index + pf2_vram_ptr;
  72.  
  73.     tile=m107_vram_data[tile_index]+(m107_vram_data[tile_index+1]<<8);
  74.     if (m107_vram_data[tile_index+3] & 0x10) tile+=0x10000;
  75.     color=m107_vram_data[tile_index+2];
  76.  
  77.     SET_TILE_INFO(0,tile,color&0x7f)
  78.  
  79.     tile_info.priority = ((m107_vram_data[tile_index+3]&2)>>1);
  80.     tile_info.flags = TILE_FLIPYX((m107_vram_data[tile_index+3] & 0xc)>>2);
  81. }
  82.  
  83. static void get_pf3_tile_info(int tile_index)
  84. {
  85.     int tile,color;
  86.     tile_index = 4*tile_index + pf3_vram_ptr;
  87.  
  88.     tile=m107_vram_data[tile_index]+(m107_vram_data[tile_index+1]<<8);
  89.     if (m107_vram_data[tile_index+3] & 0x10) tile+=0x10000;
  90.     color=m107_vram_data[tile_index+2];
  91.  
  92.     SET_TILE_INFO(0,tile,color&0x7f)
  93.     tile_info.flags = TILE_FLIPYX((m107_vram_data[tile_index+3] & 0xc)>>2);
  94. }
  95.  
  96. static void get_pf4_tile_info(int tile_index)
  97. {
  98.     int tile,color;
  99.     tile_index = 4*tile_index + pf4_vram_ptr;
  100.  
  101.     tile=m107_vram_data[tile_index]+(m107_vram_data[tile_index+1]<<8);
  102.     if (m107_vram_data[tile_index+3] & 0x10) tile+=0x10000;
  103.     color=m107_vram_data[tile_index+2];
  104.  
  105.     SET_TILE_INFO(0,tile,color&0x7f)
  106.     tile_info.flags = TILE_FLIPYX((m107_vram_data[tile_index+3] & 0xc)>>2);
  107. }
  108.  
  109. /*****************************************************************************/
  110.  
  111. READ_HANDLER( m107_vram_r )
  112. {
  113.     return m107_vram_data[offset];
  114. }
  115.  
  116. WRITE_HANDLER( m107_vram_w )
  117. {
  118.     int a;
  119.  
  120.     m107_vram_data[offset]=data;
  121.  
  122.     /* Work out what area to dirty, potentially more than 1 */
  123.     a=offset&0xc000;
  124.     offset&=0x3fff;
  125.  
  126.     if (a==pf1_vram_ptr)
  127.         tilemap_mark_tile_dirty( pf1_layer,offset/4);
  128.  
  129.     if (a==pf2_vram_ptr)
  130.         tilemap_mark_tile_dirty( pf2_layer,offset/4);
  131.  
  132.     if (a==pf3_vram_ptr)
  133.         tilemap_mark_tile_dirty( pf3_layer,offset/4);
  134.  
  135.     if (a==pf4_vram_ptr)
  136.         tilemap_mark_tile_dirty( pf4_layer,offset/4);
  137. }
  138.  
  139. /*****************************************************************************/
  140.  
  141. WRITE_HANDLER( m107_control_w )
  142. {
  143.     static int last_pf1,last_pf2,last_pf3,last_pf4;
  144.  
  145.     m107_control[offset]=data;
  146.  
  147.     switch (offset) {
  148.         case 0x10: /* Playfield 1 (top layer) */
  149.         case 0x11:
  150.             if ((m107_control[0x10]&0x80)==0x80) pf1_enable=0; else pf1_enable=1;
  151.             if ((m107_control[0x10]&0x02)==0x02) pf1_rowscroll=1; else pf1_rowscroll=0;
  152.             tilemap_set_enable(pf1_layer,pf1_enable);
  153.             pf1_vram_ptr=(m107_control[0x11]&0xf)*0x1000;
  154.             /* Have to dirty tilemaps if vram pointer has changed */
  155.             if (last_pf1!=pf1_vram_ptr)
  156.                 tilemap_mark_all_tiles_dirty(pf1_layer);
  157.             last_pf1=pf1_vram_ptr;
  158.             break;
  159.  
  160.         case 0x12: /* Playfield 2 */
  161.         case 0x13:
  162.             if ((m107_control[0x12]&0x80)==0x80) pf2_enable=0; else pf2_enable=1;
  163.             if ((m107_control[0x12]&0x02)==0x02) pf2_rowscroll=1; else pf2_rowscroll=0;
  164.             tilemap_set_enable(pf2_layer,pf2_enable);
  165.             pf2_vram_ptr=(m107_control[0x13]&0xf)*0x1000;
  166.             /* Have to dirty tilemaps if vram pointer has changed */
  167.             if (last_pf2!=pf2_vram_ptr)
  168.                 tilemap_mark_all_tiles_dirty(pf2_layer);
  169.             last_pf2=pf2_vram_ptr;
  170.             break;
  171.  
  172.         case 0x14: /* Playfield 3 */
  173.         case 0x15:
  174.             if ((m107_control[0x14]&0x80)==0x80) pf3_enable=0; else pf3_enable=1;
  175.             if ((m107_control[0x14]&0x02)==0x02) pf3_rowscroll=1; else pf3_rowscroll=0;
  176.             tilemap_set_enable(pf3_layer,pf3_enable);
  177.             pf3_vram_ptr=(m107_control[0x15]&0xf)*0x1000;
  178.             /* Have to dirty tilemaps if vram pointer has changed */
  179.             if (last_pf3!=pf3_vram_ptr)
  180.                 tilemap_mark_all_tiles_dirty(pf3_layer);
  181.             last_pf3=pf3_vram_ptr;
  182.             break;
  183.  
  184.         case 0x16: /* Playfield 4 */
  185.         case 0x17:
  186.             if ((m107_control[0x16]&0x80)==0x80) pf4_enable=0; else pf4_enable=1;
  187.             if ((m107_control[0x16]&0x02)==0x02) pf4_rowscroll=1; else pf4_rowscroll=0;
  188.             tilemap_set_enable(pf4_layer,pf4_enable);
  189.             pf4_vram_ptr=(m107_control[0x17]&0xf)*0x1000;
  190.             /* Have to dirty tilemaps if vram pointer has changed */
  191.             if (last_pf4!=pf4_vram_ptr)
  192.                 tilemap_mark_all_tiles_dirty(pf4_layer);
  193.             last_pf4=pf4_vram_ptr;
  194.             break;
  195.  
  196.         case 0x1e:
  197.         case 0x1f:
  198.             m107_raster_irq_position=((m107_control[0x1f]<<8) | m107_control[0x1e])-128;
  199.             break;
  200.     }
  201. }
  202.  
  203. /*****************************************************************************/
  204.  
  205. int m107_vh_start(void)
  206. {
  207.     pf1_layer = tilemap_create(
  208.         get_pf1_tile_info,tilemap_scan_rows,
  209.         TILEMAP_TRANSPARENT,// | TILEMAP_SPLIT,
  210.         8,8,
  211.         64,64
  212.     );
  213.  
  214.     pf2_layer = tilemap_create(
  215.         get_pf2_tile_info,tilemap_scan_rows,
  216.         TILEMAP_TRANSPARENT,// | TILEMAP_SPLIT,
  217.         8,8,
  218.         64,64
  219.     );
  220.  
  221.     pf3_layer = tilemap_create(
  222.         get_pf3_tile_info,tilemap_scan_rows,
  223.         TILEMAP_TRANSPARENT,
  224.         8,8,
  225.         64,64
  226.     );
  227.  
  228.     pf4_layer = tilemap_create(
  229.         get_pf4_tile_info,tilemap_scan_rows,
  230.         0,
  231.         8,8,
  232.         64,64
  233.     );
  234.  
  235.     if (!pf1_layer || !pf2_layer || !pf3_layer || !pf4_layer)
  236.         return 1;
  237.  
  238.     pf1_layer->transparent_pen = 0;
  239.     pf2_layer->transparent_pen = 0;
  240.     pf3_layer->transparent_pen = 0;
  241. //    pf1_layer->transmask[0] = 0x00ff;
  242. //    pf1_layer->transmask[1] = 0xff00;
  243. //    pf2_layer->transmask[0] = 0x00ff;
  244. //    pf2_layer->transmask[1] = 0xff00;
  245. //    pf3_layer->transmask[0] = 0x00ff;
  246. //    pf3_layer->transmask[1] = 0xff00;
  247.  
  248.     pf1_vram_ptr=pf2_vram_ptr=pf3_vram_ptr=pf4_vram_ptr=0;
  249.     pf1_enable=pf2_enable=pf3_enable=pf4_enable=0;
  250.     pf1_rowscroll=pf2_rowscroll=pf3_rowscroll=pf4_rowscroll=0;
  251.  
  252.     m107_spriteram = malloc(0x1000);
  253.     memset(m107_spriteram,0,0x1000);
  254.  
  255.     m107_sprite_list=0;
  256.  
  257.     return 0;
  258. }
  259.  
  260. void m107_vh_stop(void)
  261. {
  262.     free(m107_spriteram);
  263. }
  264.  
  265. /*****************************************************************************/
  266.  
  267. static void mark_sprite_colours(void)
  268. {
  269.     int offs,color,i,pal_base,colmask[128];
  270.     unsigned int *pen_usage; /* Save some struct derefs */
  271.  
  272.     pal_base = Machine->drv->gfxdecodeinfo[1].color_codes_start;
  273.     pen_usage=Machine->gfx[1]->pen_usage;
  274.     for (color = 0;color < 128;color++) colmask[color] = 0;
  275.  
  276.     for (offs = 0x1000-8;offs >= 0;offs -= 8)
  277.     {
  278.         int sprite,x_multi,multi;
  279.  
  280.         sprite=m107_spriteram[offs+2] | (m107_spriteram[offs+3]<<8);
  281.         color=m107_spriteram[offs+4]&0x7f;
  282.         x_multi=(m107_spriteram[offs+1]>>3)&0x3;
  283.         x_multi=1 << x_multi; /* 1, 2, 4 or 8 */
  284.         multi=8*x_multi;
  285.  
  286.         for (i=0; i<multi; i++)
  287.             colmask[color] |= pen_usage[(sprite + i)&0x7fff];
  288.     }
  289.  
  290.     for (color = 0;color < 128;color++)
  291.     {
  292.         for (i = 1;i < 16;i++)
  293.         {
  294.             if (colmask[color] & (1 << i))
  295.                 palette_used_colors[pal_base + 16 * color + i] = PALETTE_COLOR_USED;
  296.         }
  297.     }
  298. }
  299.  
  300. static void m107_drawsprites(struct osd_bitmap *bitmap, const struct rectangle *clip, int pri)
  301. {
  302.     int offs;
  303.  
  304.     for (offs = 0x1000-8;offs >= 0;offs -= 8) {
  305.         int x,y,sprite,colour,fx,fy,x_multi,y_multi,i,j,s_ptr;
  306.  
  307.         if (((m107_spriteram[offs+4]&0x80)==0x80) && pri==0) continue;
  308.         if (((m107_spriteram[offs+4]&0x80)==0x00) && pri==1) continue;
  309.  
  310.         y=m107_spriteram[offs+0] | (m107_spriteram[offs+1]<<8);
  311.         x=m107_spriteram[offs+6] | (m107_spriteram[offs+7]<<8);
  312.         x&=0x1ff;
  313.         y&=0x1ff;
  314.  
  315.         if (x==0 || y==0) continue; /* offscreen */
  316.  
  317.         sprite=(m107_spriteram[offs+2] | (m107_spriteram[offs+3]<<8))&0x7fff;
  318.  
  319.         x = x - 16;
  320.         y = 512 - 16 - y;
  321.  
  322.         colour=m107_spriteram[offs+4]&0x7f;
  323.         fx=m107_spriteram[offs+5]&1;
  324.         fy=m107_spriteram[offs+5]&2;
  325.         y_multi=(m107_spriteram[offs+1]>>3)&0x3;
  326.         x_multi=(m107_spriteram[offs+1]>>3)&0x3;
  327.  
  328.         /* This game doesn't seem to use X-multi */
  329.         y_multi=1 << y_multi; /* 1, 2, 4 or 8 */
  330.         x_multi=1;// << x_multi; /* 1, 2, 4 or 8 */
  331.  
  332.         if (fx && x_multi>1) x+=16;
  333.         for (j=0; j<x_multi; j++)
  334.         {
  335.             s_ptr=8 * j;
  336.             if (!fy) s_ptr+=y_multi-1;
  337.  
  338.             for (i=0; i<y_multi; i++)
  339.             {
  340.                 drawgfx(bitmap,Machine->gfx[1],
  341.                         sprite + s_ptr,
  342.                         colour,
  343.                         fx,fy,
  344.                         x,y-i*16,
  345.                         clip,TRANSPARENCY_PEN,0);
  346.                 if (fy) s_ptr++; else s_ptr--;
  347.             }
  348.             if (fx) x-=16; else x+=16;
  349.         }
  350.     }
  351. }
  352.  
  353. /*****************************************************************************/
  354.  
  355. void m107_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  356. {
  357.     /* Nothing - screen refresh is handled by raster interrupt routine */
  358. }
  359.  
  360. /*****************************************************************************/
  361.  
  362. static void m107_update_scroll_positions(void)
  363. {
  364.     int i;
  365.  
  366.     /*    Playfield 4 rowscroll data is 0xde800 - 0xdebff???
  367.         Playfield 3 rowscroll data is 0xdf800 - 0xdfbff
  368.         Playfield 2 rowscroll data is 0xdf400 - 0xdf7ff
  369.         Playfield 1 rowscroll data is 0xde800 - 0xdebff        ??
  370.     */
  371.  
  372.     if (pf1_rowscroll) {
  373.         tilemap_set_scroll_rows(pf1_layer,512);
  374.         for (i=0; i<1024; i+=2)
  375.             tilemap_set_scrollx( pf1_layer,i/2, (m107_vram_data[0xe800+i]+(m107_vram_data[0xe801+i]<<8)));
  376.     } else {
  377.         tilemap_set_scroll_rows(pf1_layer,1);
  378.         tilemap_set_scrollx( pf1_layer,0, (m107_control[3]<<8)+m107_control[2]+3 );
  379.     }
  380.     if (pf2_rowscroll) {
  381.         tilemap_set_scroll_rows(pf2_layer,512);
  382.         for (i=0; i<1024; i+=2)
  383.             tilemap_set_scrollx( pf2_layer,i/2, (m107_vram_data[0xf400+i]+(m107_vram_data[0xf401+i]<<8)));
  384.     } else {
  385.         tilemap_set_scroll_rows(pf2_layer,1);
  386.         tilemap_set_scrollx( pf2_layer,0, (m107_control[7]<<8)+m107_control[6]+1 );
  387.     }
  388.     if (pf3_rowscroll) {
  389.         tilemap_set_scroll_rows(pf3_layer,512);
  390.         for (i=0; i<1024; i+=2)
  391.             tilemap_set_scrollx( pf3_layer,i/2, (m107_vram_data[0xf800+i]+(m107_vram_data[0xf801+i]<<8)));
  392.     } else {
  393.         tilemap_set_scroll_rows(pf3_layer,1);
  394.         tilemap_set_scrollx( pf3_layer,0, (m107_control[11]<<8)+m107_control[10]-1 );
  395.     }
  396.     if (pf4_rowscroll) {
  397.         tilemap_set_scroll_rows(pf4_layer,512);
  398.         for (i=0; i<1024; i+=2)
  399.             tilemap_set_scrollx( pf4_layer,i/2, (m107_vram_data[0xfc00+i]+(m107_vram_data[0xfc01+i]<<8)));
  400.     } else {
  401.         tilemap_set_scroll_rows(pf4_layer,1);
  402.         tilemap_set_scrollx( pf4_layer,0, (m107_control[15]<<8)+m107_control[14]-3 );
  403.     }
  404.  
  405.     tilemap_set_scrolly( pf1_layer,0, (m107_control[1]<<8)+m107_control[0] );
  406.     tilemap_set_scrolly( pf2_layer,0, (m107_control[5]<<8)+m107_control[4] );
  407.     tilemap_set_scrolly( pf3_layer,0, (m107_control[9]<<8)+m107_control[8] );
  408.     tilemap_set_scrolly( pf4_layer,0, (m107_control[13]<<8)+m107_control[12] );
  409.  
  410. //    pf4_layer->scrolled=1;
  411. //    pf3_layer->scrolled=1;
  412. //    pf2_layer->scrolled=1;
  413. //    pf1_layer->scrolled=1;
  414. }
  415.  
  416. /*****************************************************************************/
  417.  
  418. void m107_screenrefresh(struct osd_bitmap *bitmap,const struct rectangle *clip)
  419. {
  420.     tilemap_update(ALL_TILEMAPS);
  421.  
  422.     palette_init_used_colors();
  423.     mark_sprite_colours();
  424.     if (palette_recalc())
  425.         tilemap_mark_all_pixels_dirty(ALL_TILEMAPS);
  426.  
  427.     tilemap_render(ALL_TILEMAPS);
  428.  
  429.     if (pf4_enable)
  430.         tilemap_draw(bitmap,pf4_layer,0);
  431.     else
  432.         fillbitmap(bitmap,palette_transparent_pen,clip);
  433.  
  434.     tilemap_draw(bitmap,pf3_layer,0);
  435.     tilemap_draw(bitmap,pf2_layer,0);
  436.     tilemap_draw(bitmap,pf1_layer,0);
  437.  
  438.     m107_drawsprites(bitmap,clip,0);
  439.     tilemap_draw(bitmap,pf2_layer,1);
  440.     tilemap_draw(bitmap,pf1_layer,1);
  441.  
  442.     m107_drawsprites(bitmap,clip,1);
  443.  
  444.     /* This hardware probably has more priority values - but I haven't found
  445.         any used yet */
  446. }
  447.  
  448. void m107_vh_raster_partial_refresh(struct osd_bitmap *bitmap,int start_line,int end_line)
  449. {
  450.     struct rectangle clip;
  451.  
  452.     clip.min_x = Machine->drv->visible_area.min_x;
  453.     clip.max_x = Machine->drv->visible_area.max_x;
  454.     clip.min_y = start_line+128;
  455.     clip.max_y = end_line+128;
  456.     if (clip.min_y < Machine->drv->visible_area.min_y)
  457.         clip.min_y = Machine->drv->visible_area.min_y;
  458.     if (clip.max_y > Machine->drv->visible_area.max_y)
  459.         clip.max_y = Machine->drv->visible_area.max_y;
  460.  
  461.     if (clip.max_y > clip.min_y)
  462.     {
  463.         m107_update_scroll_positions();
  464.         tilemap_set_clip(pf1_layer,&clip);
  465.         tilemap_set_clip(pf2_layer,&clip);
  466.         tilemap_set_clip(pf3_layer,&clip);
  467.         tilemap_set_clip(pf4_layer,&clip);
  468.         m107_screenrefresh(bitmap,&clip);
  469.     }
  470. }
  471.  
  472. /*****************************************************************************/
  473.  
  474. WRITE_HANDLER( m107_spritebuffer_w )
  475. {
  476.     if (offset==0) {
  477. //        logerror("%04x: buffered spriteram\n",cpu_get_pc());
  478.         memcpy(m107_spriteram,spriteram,0x1000);
  479.     }
  480. }
  481.